package reaction

import (
	"context"
	"fmt"
	"strings"

	"mall/common/cachex"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/types/forum"

	"github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetReactionLogListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetReactionLogListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetReactionLogListLogic {
	return &GetReactionLogListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *GetReactionLogListLogic) GetReactionLogList(in *forum.BaseListReq) (*forum.ReactionLogListResp, error) {
	if in.Filter == nil || len(*in.Filter) == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	field := model.ForumReactionLogColumns.PostID
	if in.PreFilterEntity != nil {
		switch *in.PreFilterEntity {
		case cachex.ForumReviewLike:
			field = model.ForumReactionLogColumns.PostID
		case cachex.ForumQuestionLike:
			field = model.ForumReactionLogColumns.TopicID
		case cachex.ForumAnswerLike:
			field = model.ForumReactionLogColumns.PostID
		case cachex.ForumQuestionReply:
			field = model.ForumReactionLogColumns.TopicID
		}
	}

	preloadMap, eagerLoadMap := modelx.ParsePreloadAndEagerLoad(in.Preload, in.EagerLoad)

	logrus.Info(fmt.Sprintf("GetReactionLogList preloadMap: %+v", preloadMap))
	// map[forumReactionLog:[PostId Status Count]] 

	logrus.Info(fmt.Sprintf("GetReactionLogList eagerLoadMap: %+v", eagerLoadMap))
	// map[]

	forumReactionLogEntityName := model.RpcEntityNames.ForumReactionLog
	_, hasSettingMap := model.RpcEntityPreloadMap[forumReactionLogEntityName]
	if !hasSettingMap {
		return &forum.ReactionLogListResp{}, nil
	}

	forumReactionLogRepositoryName := model.RepositoryNames.ForumReactionLog
	columnMap, hasColumnMap := model.RepositoryPreloadMap[forumReactionLogRepositoryName]
	if !hasColumnMap {
		return &forum.ReactionLogListResp{}, nil
	}

	var selectCols []string
	if preloadFields, hasPreloadFields := preloadMap[forumReactionLogEntityName]; hasPreloadFields {
		selectCols = modelx.ParseSelectColumns(preloadFields, columnMap)
	}

	filterMap := modelx.ParseFilter(in.Filter, columnMap)
	logrus.Info(fmt.Sprintf("GetReactionLogList filterMap: %+v", filterMap))
	// map[post_id:map[equalTo:[109]] type:map[equalTo:[column]] user_id:map[equalTo:[10021]]]
	if filterMap == nil {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	res, _, err := l.svcCtx.Reaction.GetLogs(l.ctx, model.M{
		"select": strings.Join(selectCols, ","),
		"latest": field,
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	resp := &forum.ReactionLogListResp{}
	if len(res) > 0 {
		for _, v := range res {
			resp.List = append(resp.List, &forum.ReactionLogInfo{
				Id:         pointy.GetPointer(v.ID),
				TopicId:    pointy.GetPointer(v.TopicID),
				PostId:     pointy.GetPointer(v.PostID),
				UserId:     pointy.GetPointer(v.UserID),
				Type:       pointy.GetPointer(v.Type),
				Status:     pointy.GetPointer(uint32(v.Status)),
				Count:      pointy.GetPointer(v.Count),
				CreatedAt:  pointy.GetPointer(modelx.FormatTime(v.CreatedAt, "")),
				CreateDate: pointy.GetPointer(uint32(v.CreateDate)),
			})
		}
	}

	if in.PreFilter != nil {
		preFilterMap := modelx.ParseFilter(in.PreFilter, columnMap)
		logrus.Info(fmt.Sprintf("GetReactionLogList preFilterMap: %+v", preFilterMap))
		if preFilterMap != nil {
			list, _, err := l.svcCtx.Reaction.GetLogs(l.ctx, model.M{
				"select": strings.Join(selectCols, ","),
				"latest": field,
			}, -1, preFilterMap)
			if err != nil {
				return nil, err
			}

			if len(list) > 0 {
				for _, v := range list {
					resp.Extra = append(resp.Extra, &forum.ReactionLogInfo{
						Id:         pointy.GetPointer(v.ID),
						TopicId:    pointy.GetPointer(v.TopicID),
						PostId:     pointy.GetPointer(v.PostID),
						UserId:     pointy.GetPointer(v.UserID),
						Type:       pointy.GetPointer(v.Type),
						Status:     pointy.GetPointer(uint32(v.Status)),
						Count:      pointy.GetPointer(v.Count),
						CreatedAt:  pointy.GetPointer(modelx.FormatTime(v.CreatedAt, "")),
						CreateDate: pointy.GetPointer(uint32(v.CreateDate)),
					})
				}
			}
		}
	}

	return resp, nil
}
